home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / pas_0593.zip / CYC-RAND.PAS < prev    next >
Pascal/Delphi Source File  |  1993-05-30  |  3KB  |  79 lines

  1. {─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
  2. Msg  : 220 of 288                                                               
  3. From : Dj Murdoch                          1:221/177.40         23 Feb 92  19:06 
  4. To   : All                                                                       
  5. Subj : Running random numbers backwards                                       
  6. ────────────────────────────────────────────────────────────────────────────────
  7. I've often thought that it would be handy to make the TP random number generator
  8. back up.  For example, if you call randomize, and then your program bombs, it's 
  9. sometimes hard to make the error repeat itself.  If you could just back up to
  10. just before the error, you might be able to figure out what's going wrong.
  11.  
  12. If you can predict the problem, probably the best way is just to save Randseed
  13. every now and then.  If you restore it to an earlier value, then the sequence of
  14. random numbers that are generated will repeat exactly.
  15.  
  16. However, just for fun, I decided today to work out the method of actually
  17. running it backwards.  That is, given no saved information, the routine below
  18. can back up the random number generator any number of steps.  
  19.  
  20. I also wrote down the forward algorithm, for completeness and to show it
  21. explicitly.  It would be faster just to call Random(2) several times, but
  22. perhaps less enlightening.
  23.  
  24. Anyways, the first procedure below is the result.  It lets you cycle the random 
  25. number generator either forwards or backwards.  A demonstration follows, in
  26. which 5 random numbers are generated, then generated again in reverse order.}
  27.  
  28.  
  29.   { Demonstration program to show how the TP 6.0 random number generator
  30.     updates System.Randseed.  Allows the seed to be cycled backwards. }
  31.  
  32.   { Written for the public domain by D.J. Murdoch, February 1992.     }
  33.  
  34.   procedure CycleRandseed(cycles:integer);
  35.   { For cycles > 0, mimics cycles calls to the TP random number generator.
  36.     For cycles < 0, backs it up the given number of calls. }
  37.   var
  38.     i : integer;
  39.   begin
  40.     if cycles > 0 then
  41.       for i := 1 to cycles do
  42.         system.randseed := system.randseed*134775813 + 1
  43.     else
  44.       for i := -1 downto cycles do
  45.         system.randseed := (system.randseed-1)*(-649090867);
  46.   end;
  47.  
  48.   var
  49.     i : integer;
  50.   begin
  51.     randomize;
  52.     writeln('Forwards:');
  53.     for i:=1 to 5 do
  54.       writeln(random);
  55.  
  56.     writeln('Backwards:');
  57.     for i:=1 to 5 do
  58.     begin
  59.       CycleRandseed(-1);    { Back to previous value }
  60.       writeln(random);      { Show it }
  61.       CycleRandseed(-1);    { Back up over it again }
  62.     end;
  63.   end.
  64.  
  65. By the way, the magic numbers in the CycleRandseed routine were kind of fun to
  66. work out.  The TP RTL includes code optimized for multiplying by 134775813, but 
  67. doesn't give the -649090867 number required to go backwards.  
  68.  
  69. To get that, I had a race with my 486-33.  I set it trying all possible longint 
  70. values until it found one which, when multiplied by 134775813 would give 1. In
  71. the meantime, I tried to work out a smarter way of solving the equation
  72.  
  73.   134775813 * X = 1 mod 2^32
  74.  
  75. for X.
  76.  
  77. I managed to work out a neat way to do it in a spreadsheet, so I won the race.  
  78. Anyone interested in puzzles should try it. 
  79.